#include "SyntaxNode.h"
//necessary
#include "memory-tools.h"
#include "main-tools.h"
#include <stdlib.h>
#include <string.h>

PSyntaxNode initSyntaxNode(NodeType _type,LexVal _value){
	PSyntaxNode result=mallocMemory(sizeof(SyntaxNode),"SyntaxNode.c:initGenericSyntaxNode:1");
	result->type=_type;
	//if it is a integer, the value is copied. If it is a string in the lexer the copy of the yytext is already done, so a new copy is useless
	result->value=_value;
	result->child=NULL;
	result->brother=NULL;
	return result;
}

PSyntaxNode initNTN(NodeType _type){
	return initSyntaxNode(_type,LEXVAL_NULL);
}

PSyntaxNode initIDNode(LexVal _value){
	return initSyntaxNode(NODE_ID,_value);
}

PSyntaxNode initTerminalNode(NodeType type){
	return initSyntaxNode(type,LEXVAL_NULL);
}


PSyntaxNode initIntConstantNode(LexVal _value){
	return initSyntaxNode(NODE_INTCONST,_value);
}

PSyntaxNode initDirectIntConstantNode(int _value){
	return initSyntaxNode(NODE_INTCONST,(LexVal)_value);

}

PSyntaxNode initStringConstantNode(LexVal _value){
	return initSyntaxNode(NODE_STRINGCONST,_value);
}

//TODO testing
PSyntaxNode initCharConstantNode(LexVal _value){
	return initSyntaxNode(NODE_CHARCONST,_value);
}

//TODO testing
PSyntaxNode initBoolConstantNode(LexVal _value){
	return initSyntaxNode(NODE_BOOLCONST,_value);
}

//TODO testing
PSyntaxNode initFloatConstantNode(LexVal _value){
	return initSyntaxNode(NODE_FLOATCONST,_value);
}

//TODO testing
PSyntaxNode initWhileStatNode(PSyntaxNode pexprNode, PSyntaxNode pstatListNode){
	PSyntaxNode result=initNTN(NODE_WHILE_STAT);
	result->child=pexprNode;
	result->child->brother=initNTN(NODE_STAT_LIST);

	result->child->brother->child=pstatListNode;
	return result;
}

int getSyntaxNodeValueMeaning(PSyntaxNode _node){
	if (_node->type==NODE_ID || _node->type==NODE_STRINGCONST){
		return LEXVAL_STRING_MEANING;
	}
	if (_node->type==NODE_INTCONST || _node->type==NODE_CHARCONST){
		return LEXVAL_INTEGER_MEANING;
	}
	if (_node->type==NODE_BOOLCONST){
		return LEXVAL_BOOLEAN_MEANING;
	}
	//TODO complete float const
	if (_node->type==NODE_FLOATCONST){
		return LEXVAL_NIHIL_MEANING;
	}
	return LEXVAL_NIHIL_MEANING;
}

void printSyntaxNode(FILE* f, PSyntaxNode _node){
	fprintf(f,"type: %d (",_node->type);
	printNodeType(f,_node->type,"\\n");
	fprintf(f,")\n");
	fprintf(f,"value: ");
	printLexVal(f,_node->value,getSyntaxNodeValueMeaning(_node));
	fprintf(f,"\n");
}

//TODO testing
PSyntaxNode cloneSyntaxNode(PSyntaxNode _node){
	PSyntaxNode cloned=mallocMemory(sizeof(SyntaxNode),"SyntaxNode.c:cloneSyntaxNode:1");
	cloned->type=_node->type;
	cloned->value=_node->value;
	cloned->child=_node->child;
	cloned->brother=_node->brother;
	return cloned;
}

//TODO testing
PSyntaxNode cloneSyntaxTree(PSyntaxNode _node){
	PSyntaxNode cloned=mallocMemory(sizeof(SyntaxNode),"SyntaxNode.c:cloneFullySyntaxNode:1");
	cloned->type=_node->type;
	cloned->value=_node->value;
	if (_node->child!=NULL){
		cloned->child=cloneSyntaxTree(_node->child);
	}else{
		cloned->child=NULL;
	}
	if (_node->brother!=NULL){
		cloned->brother=cloneSyntaxTree(_node->brother);
	}else{
		cloned->brother=NULL;
	}
	return cloned;
}

//TODO testing
void freeSyntaxNode(PSyntaxNode _node){
	if (getSyntaxNodeValueMeaning(_node)==LEXVAL_STRING_MEANING){
		freeString(_node->value.sval);
	}
	_node->child=NULL;
	_node->brother=NULL;
	freeMemory(sizeof(SyntaxNode),_node);
}

//TODO testing
void freeSyntaxTree(PSyntaxNode _node){
	if (_node->child!=NULL){
		freeSyntaxTree(_node->child);
	}
	if (_node->brother!=NULL){
		freeSyntaxTree(_node->brother);
	}
	freeSyntaxNode(_node);
}
